package com.smarttiger.zero.admin.service;

import cn.hutool.cache.CacheUtil;
import cn.hutool.core.date.DateUnit;
import com.smarttiger.zero.admin.dao.InterfaceDao;
import com.smarttiger.zero.admin.dao.LogsDao;
import com.smarttiger.zero.admin.dto.MonitorDto;
import com.smarttiger.zero.admin.entity.InterfaceModel;
import com.smarttiger.zero.admin.entity.LogsModel;
import com.smarttiger.zero.admin.util.Constant;
import com.smarttiger.zero.admin.util.Message;
import com.smarttiger.zero.admin.util.ZEROCacheUtil;
import com.smarttiger.zero.admin.util.ParamNames;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class LogsService extends BaseService<LogsModel>{
    @Autowired
    LogsDao logsDao;

    @Autowired
    InterfaceDao interfaceDao;

    @PostConstruct
    public void initMethod(){
        super.setDao(logsDao);
    }

    @ParamNames("second")
    public List<MonitorDto> monitor(String second){
        if(ZEROCacheUtil.interfaceCache.get("interface")==null){
            List<InterfaceModel> all = interfaceDao.findAll();
            ZEROCacheUtil.interfaceCache.put("interface",all);
        }
        List<InterfaceModel> allITF = ZEROCacheUtil.interfaceCache.get("interface");
        List<MonitorDto> monitors = new ArrayList<>();
        Map<String,Long> codeCount = new HashMap<>();
        List<LogsModel> monitor = ZEROCacheUtil.logsCache.get("monitor");
        if(monitor != null){
            Map<String, Long> collect = monitor.stream().collect(Collectors.groupingBy(e -> e.getCode(), Collectors.counting()));
            collect.forEach((k,v)->{
                codeCount.put(k,v);
            });
        }
        for (InterfaceModel i : allITF) {
            monitors.add(new MonitorDto(
                    i.getCode(),
                    i.getName(),
                    codeCount.containsKey(i.getCode())?codeCount.get(i.getCode()):0L));
        }
        ZEROCacheUtil.logsCache = CacheUtil.newWeakCache(DateUnit.SECOND.getMillis() * Integer.valueOf(second));
       return monitors;
    }

    @Override
    public void save(LogsModel u) {
        List<LogsModel> monitor = ZEROCacheUtil.logsCache.get("monitor");
        if(monitor == null){
            monitor = new ArrayList<>();
            ZEROCacheUtil.logsCache.put("monitor",monitor);
        }
        monitor.add(u);
        super.save(u);
    }


    @ParamNames("name,page")
    public Message getLogs(String name, String page) {
        Message message = new Message();
        Pageable pageable = PageRequest.of(Integer.valueOf(page).intValue(), Constant.PAGESIZE, Sort.by(Sort.Direction.DESC,"createDate"));
        Page<LogsModel> all = logsDao.findAll(new Specification<LogsModel>() {
            @Nullable
            @Override
            public Predicate toPredicate(Root<LogsModel> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if (!StringUtils.isEmpty(name)) {
                    predicates.add(criteriaBuilder.like(root.get("name"), name + "%"));
                }
                criteriaQuery.orderBy(criteriaBuilder.desc(root.get("createDate")));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        },pageable);
        long totalElements = all.getTotalElements();
        message.setData(all.getContent());
        message.setTotal((int)totalElements);
        return message;
    }
}
